﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Reflection;
using System.IO;
using GFE.SharePoint.Attributes;
using GFE.SharePoint.Lazy;
using System.ComponentModel.Composition;

namespace GFE.SharePoint
{
    
    public class GFECompositionContainer
    {

        private static ImportDefinition BuildImportDefinition(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality)
        {

            string requiredTypeIdentity = null;
            if (type != typeof(object))
            {
                requiredTypeIdentity = AttributedModelServices.GetTypeIdentity(type);
            }

            return new ContractBasedImportDefinition(contractName, requiredTypeIdentity, null, cardinality, false, true, CreationPolicy.Any);
        }

        public static GFELazy<T> GetExport<T>()
        {
            var exports = GetExports<T>();
            return exports.Any() ? exports.First() : default(GFELazy<T>);
        }
        public static IEnumerable<GFELazy<T>> GetExports<T>()
        {
            var returnList = new List<GFELazy<T>>();
            ComposablePartCatalog catalog = AssemblyService.AssemblyPartCatalog;
            using (var container = new CompositionContainer(catalog))
            {
                var exportList = container.GetExports<T>();
                // her tester vi på attributes hvergang det skal caches..!
                // Tjek om klassen har metoder med customattributes og gem dem i GTLazy..! (JSON Metoder)
                foreach (var exportEntry in exportList)
                {
                    returnList.Add(new GFELazy<T>(exportEntry) { LoadOrder = exportEntry.Value.GetType().GetMEFAttribute<GFELoadOrderAttribute>() == null ? int.MaxValue : exportEntry.Value.GetType().GetMEFAttribute<GFELoadOrderAttribute>().LoadOrderIndex });
                }
                return returnList.OrderBy(x => x.LoadOrder);
            }
        }
        public static Export GetExportModel<T>()
        {
            ComposablePartCatalog catalog = AssemblyService.AssemblyPartCatalog;
            using (var container = new CompositionContainer(catalog))
            {
                ImportDefinition importDefinition = BuildImportDefinition(typeof(T), (Type)null, typeof(T).ToString(), ImportCardinality.ZeroOrMore);
                return container.GetExports(importDefinition, null).FirstOrDefault();
            }
        }
        public static Export GetExportModelFactory(string contractName)
        {
            ComposablePartCatalog catalog = AssemblyService.AssemblyPartCatalog;
            using (var container = new CompositionContainer(catalog))
            {
                ImportDefinition importDefinition = BuildImportDefinition(Type.GetType(contractName), (Type)null, Type.GetType(contractName).FullName, ImportCardinality.ZeroOrMore);
                return container.GetExports(importDefinition, null).FirstOrDefault();
            }
        }
    }



}
